package cn.kevinkun.KevinkunEnhance;

import java.io.IOException;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;

import com.google.appinventor.components.annotations.DesignerComponent;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.annotations.SimpleObject;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.runtime.AndroidNonvisibleComponent;
import com.google.appinventor.components.runtime.AndroidViewComponent;
import com.google.appinventor.components.runtime.Component;
import com.google.appinventor.components.runtime.ComponentContainer;
import com.google.appinventor.components.runtime.HVArrangement;
import com.google.appinventor.components.runtime.ReplForm;
import com.google.appinventor.components.runtime.util.MediaUtil;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Cap;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

@DesignerComponent(version = 5, category = ComponentCategory.EXTENSION, description = "界面增强扩展。更多信息，请访问http://www.kevinkun.cn/enhance.html", iconName = "images/extension.png", nonVisible = true)
@SimpleObject(external = true)
public final class KevinkunEnhance extends AndroidNonvisibleComponent implements Component {

	boolean isReplForm = false;
	Context context;
	float density;
	private final Activity activity;

	public KevinkunEnhance(ComponentContainer container) {
		super(container.$form());
		density = form.deviceDensity();
		context = container.$context();
		activity = container.$context();

		if (ReplForm.class.isInstance(form))
			isReplForm = true;
	}

	@SimpleFunction
	public void SetAsCard(HVArrangement layout, int color, int radius, int borderWidth, int borderColor, int padding,
			int margin, int elevation) {
		View view = layout.getView();
		if (ViewGroup.class.isInstance(view)) {
			((ViewGroup) view).getChildAt(0).setBackgroundColor(COLOR_DEFAULT);
		}

		GradientDrawable bg;
		bg = new GradientDrawable();
		bg.setColor(color);
		bg.setCornerRadius(radius * density);
		bg.setStroke((int) (borderWidth * density), borderColor);
		view.setBackground(bg);
		view.setPadding((int) (padding * density), (int) (padding * density), (int) (padding * density),
				(int) (padding * density));

		LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) view.getLayoutParams();

		lp.setMargins((int) (margin * density), (int) (margin * density), (int) (margin * density),
				(int) (margin * density));

		view.setLayoutParams(lp);

		view.setElevation(elevation * density);
		view.invalidate();
	}

	@SimpleFunction(description = "设置背景色\n" + "fillColor: 颜色列表。长度为1，背景单一颜色；长度大于1，背景渐变。\n"
			+ "orient：渐变方向。取值分为0-7.0是从左向右，1是左下到右上，以此类推")
	public void SetBgColor(AndroidViewComponent component, String fillColor, int orient) throws JSONException {
		View view = component.getView();
		if (ViewGroup.class.isInstance(view)) {
			((ViewGroup) view).getChildAt(0).setBackgroundColor(COLOR_DEFAULT);
		}

		GradientDrawable bg;
		if (!fillColor.startsWith("[")) {
			fillColor = "[" + fillColor + "]";
		}
		JSONArray colors = new JSONArray(fillColor);

		if (colors.length() == 1) {
			bg = new GradientDrawable();
			bg.setColor(colors.getInt(0));
		} else {
			int[] ints = new int[colors.length()];
			for (int i = 0; i < colors.length(); i++) {
				ints[i] = colors.getInt(i);

			}
			GradientDrawable.Orientation currentOrientation = GradientDrawable.Orientation.LEFT_RIGHT;
			switch (orient) {
			case 1:
				currentOrientation = GradientDrawable.Orientation.BL_TR;
				break;
			case 2:
				currentOrientation = GradientDrawable.Orientation.BOTTOM_TOP;
				break;
			case 3:
				currentOrientation = GradientDrawable.Orientation.BR_TL;
				break;
			case 4:
				currentOrientation = GradientDrawable.Orientation.RIGHT_LEFT;
				break;
			case 5:
				currentOrientation = GradientDrawable.Orientation.TR_BL;
				break;
			case 6:
				currentOrientation = GradientDrawable.Orientation.TOP_BOTTOM;
				break;
			case 7:
				currentOrientation = GradientDrawable.Orientation.TL_BR;
				break;

			}
			bg = new GradientDrawable(currentOrientation, ints);
			bg.setSize(50, 50);
			// gd.setShape(shape);
			bg.setGradientType(0);
		}
		view.setBackground(bg);
		view.invalidate();

	}

	@SimpleFunction(description = "设置圆角（必须提前设置背景）。\n" + "radius: 圆角半径列表。长度为4或1，分别设置4个角或者统一设为相同数值。")
	public void SetRoundCorner(AndroidViewComponent component, String radius) throws JSONException {
		View view = component.getView();

		Drawable bg = view.getBackground();

		if (GradientDrawable.class.isInstance(bg)) {
			GradientDrawable gb = (GradientDrawable) bg;
			if (!radius.startsWith("[")) {
				radius = "[" + radius + "]";
			}
			JSONArray rad = new JSONArray(radius);
			if (rad.length() == 4) {
				float[] radii = new float[8];
				for (int i = 0; i < 4; i++) {
					radii[2 * i] = rad.getInt(i) * density;
					radii[2 * i + 1] = rad.getInt(i) * density;
				}
				gb.setCornerRadii(radii);
			} else if (rad.length() == 1) {
				gb.setCornerRadius(rad.getInt(0) * density);
			}

			view.setBackground(gb);
			view.invalidate();
		} else {
			Toast.makeText(context, "BgColor not set", 0).show();
		}

	}

	@SimpleFunction(description = "设置边框（必须提前设置背景）\n" + "boarderWidth:边框宽度\n" + "borderColor:边框颜色")
	public void SetBorder(AndroidViewComponent component, int borderWidth, int borderColor) {
		View view = component.getView();

		Drawable bg = view.getBackground();
		if (GradientDrawable.class.isInstance(bg)) {
			GradientDrawable gb = (GradientDrawable) bg;
			gb.setStroke((int) (borderWidth * density), borderColor);
			view.setBackground(gb);
			view.invalidate();
		} else {
			Toast.makeText(context, "BgColor not set", 0).show();
		}
	}

	@Deprecated
	@SimpleFunction(description = "已废弃。请使用SetBgColor")
	public void SetBackground(AndroidViewComponent component, int fillColor, int borderWidth, int borderColor,
			String roundRadius) {
		View view = component.getView();

		GradientDrawable bg = new GradientDrawable();

		bg.setColor(fillColor);
		if (roundRadius.contains(",")) {
			String[] strings = roundRadius.split(",");
			float[] radii = new float[strings.length * 2];
			for (int i = 0; i < strings.length; i++) {
				radii[(i * 2)] = (Float.parseFloat(strings[i]) * this.density);
				radii[(i * 2 + 1)] = (Float.parseFloat(strings[i]) * this.density);
			}
			bg.setCornerRadii(radii);
		} else {
			bg.setCornerRadius(Float.parseFloat(roundRadius) * this.density);
		}
		bg.setStroke((int) (borderWidth * this.density), borderColor);
		view.setBackground(bg);
		view.invalidate();
	}

	@SimpleFunction(description = "设置组件的内边距\n" + "padding:边距列表，长度为4或1，分别设置四个方向为四个数值或者统一一个数值")
	public void SetPadding(AndroidViewComponent component, String padding) throws JSONException {
		View view = component.getView();
		if (!padding.startsWith("[")) {
			padding = "[" + padding + "]";
		}
		JSONArray p = new JSONArray(padding);
		if (p.length() == 4) {

			view.setPadding((int) (p.getInt(0) * density), (int) (p.getInt(1) * density), (int) (p.getInt(2) * density),
					(int) (p.getInt(3) * density));
		} else if (p.length() == 1) {
			view.setPadding((int) (p.getInt(0) * density), (int) (p.getInt(0) * density), (int) (p.getInt(0) * density),
					(int) (p.getInt(0) * density));
		}
		view.invalidate();
	}

	@SimpleFunction(description = "设置组件的外边距\n" + "margin:边距列表。长度为4或1，分别设置四个方向为四个数值或者统一一个数值")
	public void SetMargin(AndroidViewComponent component, String margin) throws JSONException {
		View view = component.getView();

		LinearLayout.LayoutParams lp;
		Object params = view.getLayoutParams();
		if (params instanceof LinearLayout.LayoutParams) {
			lp = (LinearLayout.LayoutParams) params;
			if (!margin.startsWith("[")) {
				margin = "[" + margin + "]";
			}
			JSONArray m = new JSONArray(margin);
			if (m.length() == 4) {
				lp.setMargins((int) (m.getInt(0) * density), (int) (m.getInt(1) * density),
						(int) (m.getInt(2) * density), (int) (m.getInt(3) * density));
			} else if (m.length() == 1) {
				lp.setMargins((int) (m.getInt(0) * density), (int) (m.getInt(0) * density),
						(int) (m.getInt(0) * density), (int) (m.getInt(0) * density));
			}
			view.setLayoutParams(lp);

			view.invalidate();
		}

	}

	@SimpleFunction(description = "设置剪切子组件")
	public void SetClipChildren(AndroidViewComponent component, boolean clip) {
		ViewGroup view = (ViewGroup) component.getView();
		view.setClipChildren(clip);
		view.invalidate();
	}

	@SimpleFunction(description = "设置组件的文字行间距")
	public void SetLineSpace(AndroidViewComponent component, float space) {
		TextView view = (TextView) component.getView();
		view.setLineSpacing(space, 1f);
		view.invalidate();
	}

	@SimpleFunction(description = "设置组件的文字字间距")
	public void SetLetterSpace(AndroidViewComponent component, float space) {
		TextView view = (TextView) component.getView();
		view.setLetterSpacing(space);
		view.invalidate();
	}

	@SimpleFunction(description = "设置组件的高程elevation。会在组件周围显示阴影效果（必须提前设置背景）")
	public void SetElevation(AndroidViewComponent component, float elevation) {
		View view = component.getView();
		view.setElevation(elevation * density);
		view.invalidate();

	}

	@Deprecated
	@SimpleFunction(description = "已废弃。请使用SetBgColor")
	public void SetBackgroundGradient(AndroidViewComponent component, int orient, List<Integer> colors) {

	}

	@SimpleFunction(description = "设置组件背景图片。图片路径imagePath、边框颜色borderColor、圆角半径roundRadius。\n"
			+ "圆角半径可以是一个数字（同时设置四个角），或者是四个数字用逗号隔开（顺时针分别设置左上、右上、右下、左下）。")
	public void SetBackgroundImage(AndroidViewComponent component, String imagePath, int borderWidth, int borderColor,
			String roundRadius) {
		View view = component.getView();

		try {
			BitmapDrawable drawable = MediaUtil.getBitmapDrawable(form, imagePath);
			Bitmap roundBitmap = getRoundedCornerBitmap(drawable.getBitmap(), borderColor, borderWidth, roundRadius);
			Drawable bg = new BitmapDrawable(context.getResources(), roundBitmap);
			view.setBackground(bg);
			view.invalidate();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	@SimpleFunction(description = "设置组件字体。fontName字体名以//开始表明字体在素材库")
	public void setFontTypeface(AndroidViewComponent component, String fontName) {
		TextView view = (TextView) component.getView();
		Typeface tf = Typeface.DEFAULT;
		if (fontName.startsWith("//")) {
			fontName = fontName.substring(2);
			if (isReplForm) {
				String realpath;
				String files = this.context.getExternalFilesDir(null).getPath();
				if (Build.VERSION.SDK_INT >= 29) {
					realpath = files + "/assets/" + fontName;
				} else {
					if (files.contains("wxbit")) {
						realpath = files + "/assets/" + fontName;
					} else {
						realpath = files + "/AppInventor/assets/" + fontName;
						tf = Typeface.createFromFile(realpath);
					}
				}
				tf = Typeface.createFromFile(realpath);
			} else {
				tf = Typeface.createFromAsset(this.context.getAssets(), fontName);
			}
		} else {
			if (fontName.toLowerCase().startsWith("file://")) {
				fontName = fontName.substring(7);
			}
			tf = Typeface.createFromFile(fontName);
		}
		view.setTypeface(tf);
		view.requestLayout();

	}

	private Bitmap getRoundedCornerBitmap(Bitmap bitmap, int borderColor, int borderWidth, String roundRadius) {

		Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);
		Canvas canvas = new Canvas(output);
		int w = bitmap.getWidth();
		int h = bitmap.getHeight();

		final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
		canvas.drawARGB(0, 0, 0, 0);

		float[] radii = new float[4];
		if (roundRadius.contains(",")) {
			String[] strings = roundRadius.split(",");
			for (int i = 0; i < 4; i++) {
				radii[i] = Float.parseFloat(strings[i]) * density;
			}
		} else {
			for (int i = 0; i < 4; i++) {
				radii[i] = Float.parseFloat(roundRadius) * density;
			}
		}

		Rect rect = new Rect(0, 0, w, h);

		Path path = new Path();
		path.moveTo(radii[0], 0);
		path.lineTo(w - radii[1], 0);
		path.arcTo(w - radii[1], 0, w, radii[1], 270, 90, false);
		path.lineTo(w, h - radii[2]);
		path.arcTo(w - radii[2], h - radii[2], w, h, 0, 90, false);
		path.lineTo(radii[3], h);
		path.arcTo(0, h - radii[3], radii[3], h, 90, 90, false);
		path.lineTo(0, radii[0]);
		path.arcTo(0, 0, radii[0], radii[0], 180, 90, false);
		path.close();

		canvas.drawPath(path, paint);
		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(bitmap, rect, rect, paint);

		if (borderWidth != 0) {
			float b = borderWidth * density;
			path.reset();

			path.moveTo(radii[0] / 2, b / 2);
			path.lineTo(w - radii[1] / 2, b / 2);
			path.arcTo(w - radii[1], b / 2, w - b / 2, radii[1], 270, 90, false);

			path.moveTo(w - b / 2, radii[1] / 2);
			path.lineTo(w - b / 2, h - radii[2] / 2);
			path.arcTo(w - radii[2], h - radii[2], w - b / 2, h - b / 2, 0, 90, false);

			path.moveTo(w - radii[2] / 2, h - b / 2);
			path.lineTo(radii[3] / 2, h - b / 2);
			path.arcTo(b / 2, h - radii[3], radii[3], h - b / 2, 90, 90, false);

			path.moveTo(b / 2, h - radii[3] / 2);
			path.lineTo(b / 2, radii[0] / 2);
			path.arcTo(b / 2, b / 2, radii[0], radii[0], 180, 90, false);
			// path.close();

			paint.setColor(borderColor);
			paint.setStrokeWidth(b);
			paint.setStyle(Style.STROKE);
			paint.setStrokeCap(Cap.ROUND);
			paint.setXfermode(new PorterDuffXfermode(Mode.SRC_OVER));
			canvas.drawPath(path, paint);
		}

		return output;

	}

	@SimpleFunction
	public void FullScreen() {
		// 隐藏虚拟按键，并且全屏
		if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) { // lower api
			View v = activity.getWindow().getDecorView();
			v.setSystemUiVisibility(View.GONE);
		} else if (Build.VERSION.SDK_INT >= 19) {
			// for new api versions.
			View decorView = activity.getWindow().getDecorView();
			int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
					| View.SYSTEM_UI_FLAG_FULLSCREEN;

			decorView.setSystemUiVisibility(uiOptions);
		}
	}

}